home *** CD-ROM | disk | FTP | other *** search
- /*
- dwarf_frame.c
-
- This file implements the API relating to frames
- contained in the debug_frame section.
-
- $Revision: 1.36 $ $Date: 1994/07/05 21:59:37 $
- */
-
-
- #include <stdio.h>
- #include "dwarf_incl.h"
- #include "dwarf_frame.h"
- #include "dwarf_arange.h" /* using Arange as a way to build a list*/
-
-
- /*
- This function is the heart of the debug_frame stuff. Don't even
- think of reading this without reading both the Libdwarf and
- consumer API carefully first. This function basically executes
- frame instructions contained in a Cie or an Fde, but does in a
- number of different ways depending on the information sought.
- Start_instr_ptr points to the first byte of the frame instruction
- stream, and final_instr_ptr to the to the first byte after the
- last.
-
- The offsets returned in the frame instructions are factored. That
- is they need to be multiplied by either the code_alignment_factor
- or the data_alignment_factor, as appropriate to obtain the actual
- offset. This makes it possible to expand an instruction stream
- without the corresponding Cie. However, when an Fde frame instr
- sequence is being expanded there must be a valid Cie with a pointer
- to an initial table row.
-
- If unsuccessful (there is an error) this function
- returns a negative number (an error code).
- If successful and make_instr is false it returns 1.
- If successful and make_instr is true,
- it returns the number of frame instructions executed.
- It does not do a whole lot of input validation being a private
- function. Please make sure inputs are valid.
-
- (1) If make_instr is true, it makes a list of pointers to
- Dwarf_Frame_Op structures containing the frame instructions
- executed. A pointer to this list is returned in ret_frame_instr.
- Make_instr is true only when a list of frame instructions is to be
- returned. In this case since we are not interested in the contents
- of the table, the input Cie can be NULL. This is the only case
- where the inpute Cie can be NULL.
-
- (2) If search_pc is true, frame instructions are executed till
- either a location is reached that is greater than the search_pc_val
- provided, or all instructions are executed. At this point the
- last row of the table generated is returned in a structure.
- A pointer to this structure is supplied in table.
-
- (3) This function is also used to create the initial table row
- defined by a Cie. In this case, the Dwarf_Cie pointer cie, is
- NULL. For an FDE, however, cie points to the associated Cie.
- */
- static Dwarf_Sword
- _dwarf_exec_frame_instr (
- Dwarf_Bool make_instr, /* Make list of frame instr? */
- Dwarf_Frame_Op **ret_frame_instr, /* Ptr to list of ptrs to fr instrs */
- Dwarf_Bool search_pc, /* Search for a pc value? */
- Dwarf_Addr search_pc_val, /* Search for this pc value */
- Dwarf_Addr loc, /* initial location value */
- Dwarf_Small *start_instr_ptr, /* Ptr to start of frame instrs. */
- Dwarf_Small *final_instr_ptr, /* Ptr just past frame instrs. */
- Dwarf_Frame table, /* Ptr to struct with last row. */
- Dwarf_Cie cie, /* Ptr to Cie used by the Fde. */
- Dwarf_Debug dbg /* Associated Dwarf_Debug */
- )
- {
- /* Sweeps the frame instructions. */
- Dwarf_Small *instr_ptr;
-
- /* Obvious from the documents. */
- Dwarf_Small instr, opcode;
- Dwarf_Small reg_no, reg_noA, reg_noB;
- Dwarf_Unsigned factored_N_value;
- Dwarf_Addr new_loc;
- Dwarf_Unsigned adv_loc;
-
- struct Dwarf_Reg_Rule_s reg[DW_FRAME_LAST_REG_NUM];
-
- /* This is used to end executing frame instructions. */
- /* Becomes true when search_pc is true and loc */
- /* is greater than search_pc_val. */
- Dwarf_Bool search_over = false;
-
- /* Used by the DW_FRAME_advance_loc instr */
- /* to hold the increment in pc value. */
- Dwarf_Addr adv_pc;
-
- /* Contains the length in bytes of */
- /* an leb128 encoded number. */
- Dwarf_Word leb128_length;
-
- /* Counts the number of frame instructions executed. */
- Dwarf_Word instr_count = 0;
-
- /*
- These contain the current fields
- of the current frame instruction.
- */
- Dwarf_Small fp_base_op = 0;
- Dwarf_Small fp_extended_op;
- Dwarf_Half fp_register;
- Dwarf_Unsigned fp_offset;
- Dwarf_Off fp_instr_offset;
-
- /*
- Stack_table points to the row (Dwarf_Frame ie) being
- pushed or popped by a remember or restore instruction.
- Top_stack points to the top of the stack of rows.
- */
- Dwarf_Frame stack_table;
- Dwarf_Frame top_stack = NULL;
-
- /*
- These are used only when make_instr is true.
- Curr_instr is a pointer to the current frame
- instruction executed. Curr_instr_ptr,
- head_instr_list, and curr_instr_list are used
- to form a chain of Dwarf_Frame_Op structs.
- Dealloc_instr_ptr is used to deallocate the
- structs used to form the chain. Head_instr_block
- points to a contiguous list of pointers to the
- Dwarf_Frame_Op structs executed.
- */
- Dwarf_Frame_Op *curr_instr;
- Dwarf_Chain curr_instr_item, dealloc_instr_item;
- Dwarf_Chain head_instr_chain = NULL;
- Dwarf_Chain tail_instr_chain = NULL;
- Dwarf_Frame_Op *head_instr_block;
-
- /*
- These are the alignment_factors taken from the
- Cie provided. When no input Cie is provided they
- are set to 1, because only factored offsets are
- required.
- */
- Dwarf_Sword code_alignment_factor = 1;
- Dwarf_Sword data_alignment_factor = 1;
-
- /*
- This flag indicates when an actual alignment factor
- is needed. So if a frame instruction that computes
- an offset using an alignment factor is encountered
- when this flag is set, an error is returned because
- the Cie did not have a valid augmentation.
- */
- Dwarf_Bool need_augmentation = false;
-
- Dwarf_Word i;
-
- /* Initialize first row from associated Cie. */
- if (cie != NULL && cie->ci_initial_table != NULL) {
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
- reg[i] = cie->ci_initial_table->fr_reg[i];
- }
- else { /* initialize with same_value */
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++) {
- reg[i].ru_is_off = 0;
- reg[i].ru_register = DW_FRAME_SAME_VAL;
- reg[i].ru_offset = 0;
- }
- }
-
- /*
- The idea here is that the code_alignment_factor and
- data_alignment_factor which are needed for certain
- instructions are valid only when the Cie has a proper
- augmentation string. So if the augmentation is not
- right, only Frame instruction can be read.
- */
- if (cie != NULL && cie->ci_augmentation != NULL) {
- code_alignment_factor = cie->ci_code_alignment_factor;
- data_alignment_factor = cie->ci_data_alignment_factor;
- }
- else need_augmentation = !make_instr;
-
- instr_ptr = start_instr_ptr;
- while (instr_ptr < final_instr_ptr && !search_over) {
-
- fp_instr_offset = instr_ptr - start_instr_ptr;
- instr = *(Dwarf_Small *)instr_ptr;
- instr_ptr = instr_ptr + sizeof(Dwarf_Small);
-
- fp_base_op = (instr & 0xc0)>>6;
- if ((instr & 0xc0) == 0x00) {
- opcode = instr; /* is really extended op */
- fp_extended_op = (instr & (~(0xc0))) & 0xff;
- } else {
- opcode = instr & 0xc0; /* is base op */
- fp_extended_op = 0;
- }
-
- fp_register = 0;
- fp_offset = 0;
- switch (opcode) {
-
- case DW_CFA_advance_loc : { /* base op */
- fp_offset = adv_pc = instr & DW_FRAME_INSTR_OFFSET_MASK;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- adv_pc = adv_pc * code_alignment_factor;
-
- search_over = search_pc && (loc+adv_pc > search_pc_val);
- /* If gone past pc needed, retain old pc. */
- if (!search_over) loc = loc + adv_pc;
- break;
- }
-
- case DW_CFA_offset : { /* base op */
- reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
- if (reg_no > DW_FRAME_LAST_REG_NUM){
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- factored_N_value =
- _dwarf_decode_u_leb128(instr_ptr,&leb128_length);
- instr_ptr = instr_ptr + leb128_length;
-
- fp_register = reg_no;
- fp_offset = factored_N_value;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
-
- reg[reg_no].ru_is_off = 1;
- reg[reg_no].ru_register = DW_FRAME_CFA_COL;
- reg[reg_no].ru_offset = factored_N_value *
- data_alignment_factor;
-
- break;
- }
-
- case DW_CFA_restore : { /* base op */
- reg_no = (instr & DW_FRAME_INSTR_OFFSET_MASK);
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- fp_register = reg_no;
-
- if (cie != NULL && cie->ci_initial_table != NULL)
- reg[reg_no] = cie->ci_initial_table->fr_reg[reg_no];
- else
- if (!make_instr) return(DF_MAKE_INSTR_NO_INIT);
-
- break;
- }
- case DW_CFA_set_loc : {
- READ_UNALIGNED(new_loc, instr_ptr, dbg->de_length_size);
- instr_ptr += dbg->de_length_size;
- if (new_loc <= loc) return(DF_NEW_LOC_LESS_OLD_LOC);
-
- search_over = search_pc && (new_loc > search_pc_val);
-
- /* If gone past pc needed, retain old pc. */
- if (!search_over) loc = new_loc;
- fp_offset = new_loc;
- break;
- }
-
- case DW_CFA_advance_loc1 : {
- fp_offset = adv_loc = *(Dwarf_Small *)instr_ptr;
- instr_ptr = instr_ptr + sizeof(Dwarf_Small);
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- adv_loc *= code_alignment_factor;
-
- search_over = search_pc &&
- (loc + adv_loc > search_pc_val);
-
- /* If gone past pc needed, retain old pc. */
- if (!search_over) loc = loc + adv_loc;
- break;
- }
-
- case DW_CFA_advance_loc2 : {
- READ_UNALIGNED(adv_loc, instr_ptr, sizeof(Dwarf_Half));
- instr_ptr += sizeof(Dwarf_Half);
- fp_offset = adv_loc;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- adv_loc *= code_alignment_factor;
-
- search_over = search_pc &&
- (loc+adv_loc > search_pc_val);
-
- /* If gone past pc needed, retain old pc. */
- if (!search_over) loc = loc + adv_loc;
- break;
- }
-
- case DW_CFA_advance_loc4 : {
- READ_UNALIGNED(adv_loc, instr_ptr, sizeof(Dwarf_Word));
- instr_ptr += sizeof(Dwarf_Word);
- fp_offset = adv_loc;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- adv_loc *= code_alignment_factor;
-
- search_over = search_pc &&
- (loc+adv_loc > search_pc_val);
-
- /* If gone past pc needed, retain old pc. */
- if (!search_over) loc = loc + adv_loc;
- break;
- }
-
- case DW_CFA_offset_extended : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
- factored_N_value =
- _dwarf_decode_u_leb128(instr_ptr,&leb128_length);
- instr_ptr = instr_ptr + leb128_length;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- reg[reg_no].ru_is_off = 1;
- reg[reg_no].ru_register = DW_FRAME_CFA_COL;
- reg[reg_no].ru_offset = factored_N_value *
- data_alignment_factor;
-
- fp_register = reg_no;
- fp_offset = factored_N_value;
- break;
- }
-
- case DW_CFA_restore_extended : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- if (cie != NULL && cie->ci_initial_table != NULL)
- reg[reg_no] =
- cie->ci_initial_table->fr_reg[reg_no];
- else
- if (!make_instr) return(DF_MAKE_INSTR_NO_INIT);
-
- fp_register = reg_no;
- break;
- }
-
- case DW_CFA_undefined : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- reg[reg_no].ru_is_off = 0;
- reg[reg_no].ru_register = DW_FRAME_UNDEFINED_VAL;
- reg[reg_no].ru_offset = 0;
-
- fp_register = reg_no;
- break;
- }
-
- case DW_CFA_same_value : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- reg[reg_no].ru_is_off = 0;
- reg[reg_no].ru_register = DW_FRAME_SAME_VAL;
- reg[reg_no].ru_offset = 0;
- fp_register = reg_no;
- break;
- }
-
- case DW_CFA_register : {
- DECODE_LEB128_UWORD(instr_ptr, reg_noA)
- if (reg_noA > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
- DECODE_LEB128_UWORD(instr_ptr, reg_noB)
- if (reg_noB > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- reg[reg_noA].ru_is_off = 0;
- reg[reg_noA].ru_register = reg_noB;
- reg[reg_noA].ru_offset = 0;
-
- fp_register = reg_noA;
- fp_offset = reg_noB;
- break;
- }
-
- case DW_CFA_remember_state : {
- stack_table = (Dwarf_Frame)
- _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
- if (stack_table == NULL) return(DF_ALLOC_FAIL);
-
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
- stack_table->fr_reg[i] = reg[i];
-
- if (top_stack != NULL)
- stack_table->fr_next = top_stack;
- top_stack = stack_table;
-
- break;
- }
-
- case DW_CFA_restore_state : {
- if (top_stack == NULL) return(DF_POP_EMPTY_STACK);
- stack_table = top_stack;
- top_stack = stack_table->fr_next;
-
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
- reg[i] = stack_table->fr_reg[i];
-
- dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
- break;
- }
-
- case DW_CFA_def_cfa : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- factored_N_value =
- _dwarf_decode_u_leb128(instr_ptr,&leb128_length);
- instr_ptr = instr_ptr + leb128_length;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- reg[DW_FRAME_CFA_COL].ru_is_off = 1;
- reg[DW_FRAME_CFA_COL].ru_register = reg_no;
- reg[DW_FRAME_CFA_COL].ru_offset = factored_N_value;
-
- fp_register = reg_no;
- fp_offset = factored_N_value;
- break;
- }
-
- case DW_CFA_def_cfa_register : {
- DECODE_LEB128_UWORD(instr_ptr, reg_no)
- if (reg_no > DW_FRAME_LAST_REG_NUM) {
- return(DF_REG_NUM_TOO_HIGH);
- }
-
- reg[DW_FRAME_CFA_COL].ru_is_off = 0;
- reg[DW_FRAME_CFA_COL].ru_register = reg_no;
- reg[DW_FRAME_CFA_COL].ru_offset = 0;
- fp_register = reg_no;
- break;
- }
-
- case DW_CFA_def_cfa_offset : {
- factored_N_value =
- _dwarf_decode_u_leb128(instr_ptr,&leb128_length);
- instr_ptr = instr_ptr + leb128_length;
-
- if (need_augmentation) return(DF_NO_CIE_AUGMENTATION);
- reg[DW_FRAME_CFA_COL].ru_offset = factored_N_value;
-
- fp_offset = factored_N_value;
- break;
- }
-
- case DW_CFA_nop : {
- break;
- }
- }
-
- if (make_instr) {
- instr_count++;
-
- curr_instr = (Dwarf_Frame_Op *)
- _dwarf_get_alloc(dbg, DW_DLA_FRAME_OP, 1);
- if (curr_instr == NULL) return(DF_ALLOC_FAIL);
-
- curr_instr->fp_base_op = fp_base_op;
- curr_instr->fp_extended_op = fp_extended_op;
- curr_instr->fp_register = fp_register;
- curr_instr->fp_offset = fp_offset;
- curr_instr->fp_instr_offset = fp_instr_offset;
-
- curr_instr_item = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_instr_item == NULL) return(DF_ALLOC_FAIL);
-
- curr_instr_item->ch_item = curr_instr;
- if (head_instr_chain == NULL)
- head_instr_chain = tail_instr_chain = curr_instr_item;
- else {
- tail_instr_chain->ch_next = curr_instr_item;
- tail_instr_chain = curr_instr_item;
- }
- }
-
- }
-
- /*
- If frame instruction decoding was right
- we would stop exactly at final_instr_ptr.
- */
- if (instr_ptr > final_instr_ptr)
- return(DF_FRAME_DECODING_ERROR);
-
- /* Create the last row generated. */
- if (table != NULL) {
- table->fr_loc = loc;
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++)
- table->fr_reg[i] = reg[i];
- }
-
- /* Dealloc anything remaining on stack. */
- for (; top_stack != NULL; ) {
- stack_table = top_stack;
- top_stack = top_stack->fr_next;
- dwarf_dealloc(dbg, stack_table, DW_DLA_FRAME);
- }
-
- if (make_instr) {
- /* Allocate list of pointers to Dwarf_Frame_Op's. */
- head_instr_block = (Dwarf_Frame_Op *)
- _dwarf_get_alloc(dbg, DW_DLA_FRAME_BLOCK, instr_count);
- if (head_instr_block == NULL) return(DF_ALLOC_FAIL);
-
- /*
- Store pointers to Dwarf_Frame_Op's in this list
- and deallocate the structs that chain the
- Dwarf_Frame_Op's.
- */
- curr_instr_item = head_instr_chain;
- for (i = 0 ; i < instr_count; i++) {
- *(head_instr_block + i) =
- *(Dwarf_Frame_Op *)curr_instr_item->ch_item;
- dealloc_instr_item = curr_instr_item;
- curr_instr_item = curr_instr_item->ch_next;
- dwarf_dealloc(dbg, dealloc_instr_item->ch_item, DW_DLA_FRAME_OP);
- dwarf_dealloc(dbg, dealloc_instr_item, DW_DLA_CHAIN);
- }
- *ret_frame_instr = head_instr_block;
-
- return(instr_count);
- }
- else
- return(1);
- }
-
-
- int
- dwarf_get_fde_list (
- Dwarf_Debug dbg,
- Dwarf_Cie **cie_data,
- Dwarf_Signed *cie_element_count,
- Dwarf_Fde **fde_data,
- Dwarf_Signed *fde_element_count,
- Dwarf_Error *error
- )
- {
- /* Scans the debug_frame section. */
- Dwarf_Small *frame_ptr;
-
- /* Points to the start of the current Fde or Cie. */
- Dwarf_Small *start_frame_ptr;
-
- /* Fields for the current Cie being read. */
- Dwarf_Unsigned length; /* READ_UNALIGNED needs 8 byte dest */
- Dwarf_Unsigned offset;
- Dwarf_Small version;
- Dwarf_Small *augmentation;
- Dwarf_Word code_alignment_factor;
- Dwarf_Sword data_alignment_factor;
- Dwarf_Small return_address_register;
-
- /*
- New_cie points to the Cie being read, and
- head_cie_ptr and cur_cie_ptr are used for
- chaining them up in sequence.
- */
- Dwarf_Cie new_cie;
- Dwarf_Cie head_cie_ptr = NULL;
- Dwarf_Cie cur_cie_ptr;
- Dwarf_Word cie_count = 0;
-
- /*
- Points to a list of contiguous pointers
- to Dwarf_Cie structures.
- */
- Dwarf_Cie *cie_list_ptr;
-
- /* Fields for the current Fde being read. */
- Dwarf_Addr initial_location;
- Dwarf_Addr address_range;
-
- /*
- New_fde points to the current Fde being read,
- and head_fde_ptr and cur_fde_ptr are used to
- chain them up.
- */
- Dwarf_Fde new_fde;
- Dwarf_Fde head_fde_ptr = NULL;
- Dwarf_Fde cur_fde_ptr;
- Dwarf_Word fde_count = 0;
-
- /*
- Points to a list of contiguous pointers to
- Dwarf_Fde structures.
- */
- Dwarf_Fde *fde_list_ptr;
-
- /*
- Is used to check the offset field in the Fde
- by checking for a Cie at this address.
- */
- Dwarf_Small *fde_cie_ptr;
-
- Dwarf_Word leb128_length;
- Dwarf_Word i, j;
-
-
- frame_ptr = dbg->de_debug_frame;
-
- if(frame_ptr == 0) {
- return DW_DLV_NO_ENTRY;
- }
-
- while (frame_ptr < dbg->de_debug_frame + dbg->de_debug_frame_size) {
-
- start_frame_ptr = frame_ptr;
-
- READ_UNALIGNED(length, frame_ptr, dbg->de_length_size);
- frame_ptr += dbg->de_length_size;
- if (length % dbg->de_length_size != 0) {
- _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
- return(DW_DLV_ERROR);
- }
-
- READ_UNALIGNED(offset, frame_ptr, dbg->de_length_size);
- SIGN_EXTEND(offset, dbg->de_length_size);
-
- frame_ptr += dbg->de_length_size;
- if (offset == DW_CIE_ID) {
-
- version = *(Dwarf_Small *)frame_ptr;
- frame_ptr++;
- if (version != DW_CIE_VERSION) {
- _dwarf_error(dbg,error,DW_DLE_FRAME_VERSION_BAD);
- return(DW_DLV_ERROR);
- }
-
- if (strcmp(frame_ptr,DW_DEBUG_FRAME_AUGMENTER_STRING) != 0 &&
- strcmp(frame_ptr,DW_NULL_STRING) != 0)
- frame_ptr = start_frame_ptr + length +
- dbg->de_length_size;
- else {
- augmentation = frame_ptr;
- frame_ptr = frame_ptr + strlen(frame_ptr) + 1;
-
- DECODE_LEB128_UWORD(frame_ptr, code_alignment_factor)
-
- data_alignment_factor =
- _dwarf_decode_s_leb128(frame_ptr,&leb128_length);
- frame_ptr = frame_ptr + leb128_length;
-
- return_address_register = *(Dwarf_Small *)frame_ptr;
- if (return_address_register > DW_FRAME_LAST_REG_NUM) {
- _dwarf_error(dbg,error,DW_DLE_CIE_RET_ADDR_REG_ERROR);
- return(DW_DLV_ERROR);
- }
- frame_ptr++;
- }
-
- new_cie = (Dwarf_Cie)_dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
- if (new_cie == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
-
- new_cie->ci_length = length;
- new_cie->ci_augmentation = augmentation;
-
- new_cie->ci_data_alignment_factor = data_alignment_factor;
- new_cie->ci_code_alignment_factor = code_alignment_factor;
- new_cie->ci_return_address_register = return_address_register;
- new_cie->ci_cie_start = start_frame_ptr;
- new_cie->ci_cie_instr_start = frame_ptr;
- new_cie->ci_dbg = dbg;
-
- cie_count++;
- if (head_cie_ptr == NULL)
- head_cie_ptr = cur_cie_ptr = new_cie;
- else {
- cur_cie_ptr->ci_next = new_cie;
- cur_cie_ptr = new_cie;
- }
- } else {
- Dwarf_Small *initloc = frame_ptr;
-
- READ_UNALIGNED(initial_location, frame_ptr, dbg->de_length_size);
- frame_ptr += dbg->de_length_size;
-
- READ_UNALIGNED(address_range, frame_ptr, dbg->de_length_size);
- frame_ptr += dbg->de_length_size;
-
- new_fde = (Dwarf_Fde)_dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
- if (new_fde == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
-
- new_fde->fd_length = length;
- new_fde->fd_cie_offset = offset;
- new_fde->fd_initial_location = initial_location;
- new_fde->fd_initial_loc_pos = initloc;
- new_fde->fd_address_range = address_range;
- new_fde->fd_fde_start = start_frame_ptr;
- new_fde->fd_fde_instr_start = frame_ptr;
- new_fde->fd_dbg = dbg;
-
- fde_count++;
- if (head_fde_ptr == NULL)
- head_fde_ptr = cur_fde_ptr = new_fde;
- else {
- cur_fde_ptr->fd_next = new_fde;
- cur_fde_ptr = new_fde;
- }
- }
-
- /* Skip over instructions to start of next frame. */
- frame_ptr = start_frame_ptr + length + dbg->de_length_size;
- }
-
- if (cie_count > 0) {
- cie_list_ptr = (Dwarf_Cie *)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
- }
- else {
- return (DW_DLV_NO_ENTRY);
- }
- if (cie_list_ptr == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- /* Return arguments. */
- *cie_data = cie_list_ptr;
- *cie_element_count = cie_count;
- dbg->de_cie_data = cie_list_ptr;
- dbg->de_cie_count = cie_count;
-
- cur_cie_ptr = head_cie_ptr;
- for (i = 0; i < cie_count; i++) {
- *(cie_list_ptr + i) = cur_cie_ptr;
- cur_cie_ptr = cur_cie_ptr->ci_next;
- }
-
- if (fde_count > 0) {
- fde_list_ptr = (Dwarf_Fde *)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
- }
- else {
- return(DW_DLV_NO_ENTRY);
- }
- if (fde_list_ptr == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- /* Return arguments. */
- *fde_data = fde_list_ptr;
- *fde_element_count = fde_count;
- dbg->de_fde_data = fde_list_ptr;
- dbg->de_fde_count = fde_count;
-
- cur_fde_ptr = head_fde_ptr;
- for (i = 0; i < fde_count; i++) {
- *(fde_list_ptr + i) = cur_fde_ptr;
-
- fde_cie_ptr = (Dwarf_Small *)(dbg->de_debug_frame +
- cur_fde_ptr->fd_cie_offset);
- for (j = 0; j < cie_count; j++)
- if (((Dwarf_Cie)*(cie_list_ptr+j))->ci_cie_start == fde_cie_ptr)
- break;
- if (j == cie_count) {
- _dwarf_error(dbg,error,DW_DLE_NO_CIE_FOR_FDE);
- return(DW_DLV_ERROR);
- }
- else {
- cur_fde_ptr->fd_cie_index = j;
- cur_fde_ptr->fd_cie = *(cie_list_ptr + j);
- }
-
- cur_fde_ptr = cur_fde_ptr->fd_next;
- }
-
- return(DW_DLV_OK);
- }
-
- int
- dwarf_get_fde_for_die(
- Dwarf_Debug dbg,
- Dwarf_Die die,
- Dwarf_Fde * ret_fde,
- Dwarf_Error *error
- )
- {
- Dwarf_Attribute attr;
- Dwarf_Unsigned fde_offset;
- Dwarf_Signed signdval;
- Dwarf_Unsigned length;
- Dwarf_Signed offset;
- Dwarf_Sword temp_offset;
- Dwarf_Addr initial_location;
- Dwarf_Addr address_range;
- Dwarf_Fde new_fde;
- char *fde_ptr;
- char *cie_ptr;
- char *start_cie_ptr;
- Dwarf_Cie new_cie;
-
- /* Fields for the current Cie being read. */
- Dwarf_Small version;
- Dwarf_Small *augmentation;
- Dwarf_Word code_alignment_factor;
- Dwarf_Sword data_alignment_factor;
- Dwarf_Small return_address_register;
- int resattr;
- int sdatares;
-
- Dwarf_Word leb128_length;
-
- if (die == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DIE_NULL);
- return(DW_DLV_ERROR);
- }
-
- resattr = dwarf_attr(die, DW_AT_MIPS_fde,&attr, error);
- if(resattr != DW_DLV_OK) {
- return resattr;
- }
-
- /* why is this formsdata? FIX*/
- sdatares = dwarf_formsdata(attr,&signdval,error);
- if(sdatares != DW_DLV_OK){
- return sdatares;
- }
- fde_offset = signdval;
- fde_ptr = dbg->de_debug_frame+fde_offset;
-
- READ_UNALIGNED(length, fde_ptr, dbg->de_length_size);
- fde_ptr += dbg->de_length_size;
-
- if (length % dbg->de_length_size != 0) {
- _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
- return( DW_DLV_ERROR);
- }
-
- READ_UNALIGNED(offset, fde_ptr, dbg->de_length_size);
- SIGN_EXTEND(offset, dbg->de_length_size);
- fde_ptr += dbg->de_length_size;
-
- READ_UNALIGNED(initial_location, fde_ptr, dbg->de_length_size);
- fde_ptr += dbg->de_length_size;
-
- READ_UNALIGNED(address_range, fde_ptr, dbg->de_length_size);
- fde_ptr += dbg->de_length_size;
-
- new_fde = (Dwarf_Fde)_dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
- if (new_fde == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
-
- new_fde->fd_length = length;
- new_fde->fd_cie_offset = offset;
- new_fde->fd_initial_location = initial_location;
- new_fde->fd_address_range = address_range;
- new_fde->fd_fde_start = dbg->de_debug_frame+fde_offset;
- new_fde->fd_fde_instr_start = fde_ptr;
- new_fde->fd_dbg = dbg;
-
- /* now read the cie corresponding to the fde */
- cie_ptr = dbg->de_debug_frame+offset;
- start_cie_ptr = cie_ptr;
-
- READ_UNALIGNED(length, cie_ptr, dbg->de_length_size);
- cie_ptr += dbg->de_length_size;
-
- if (length % dbg->de_length_size != 0) {
- _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
- return(DW_DLV_ERROR);
- }
-
- READ_UNALIGNED(offset, cie_ptr, dbg->de_length_size);
- SIGN_EXTEND(offset, dbg->de_length_size);
- cie_ptr += dbg->de_length_size;
-
- if (offset == DW_CIE_ID) {
- version = *(Dwarf_Small *)cie_ptr;
- cie_ptr++;
- if (version != DW_CIE_VERSION) {
- _dwarf_error(dbg,error,DW_DLE_FRAME_VERSION_BAD);
- return(DW_DLV_ERROR);
- }
- if (strcmp(cie_ptr,DW_DEBUG_FRAME_AUGMENTER_STRING) != 0 &&
- strcmp(cie_ptr,DW_NULL_STRING) != 0)
- cie_ptr = start_cie_ptr + length +
- dbg->de_length_size;
- else {
- augmentation = cie_ptr;
- cie_ptr = cie_ptr + strlen(cie_ptr) + 1;
-
- DECODE_LEB128_UWORD(cie_ptr, code_alignment_factor)
-
- data_alignment_factor =
- _dwarf_decode_s_leb128(cie_ptr,&leb128_length);
- cie_ptr = cie_ptr + leb128_length;
-
- return_address_register = *(Dwarf_Small *)cie_ptr;
- if (return_address_register > DW_FRAME_LAST_REG_NUM) {
- _dwarf_error(dbg,error,DW_DLE_CIE_RET_ADDR_REG_ERROR);
- return( DW_DLV_ERROR);
- }
- cie_ptr++;
- }
-
- new_cie = (Dwarf_Cie)_dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
- if (new_cie == NULL) {
- _dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
-
- new_cie->ci_initial_table = NULL;
- new_cie->ci_length = length;
- new_cie->ci_augmentation = augmentation;
- new_cie->ci_data_alignment_factor = data_alignment_factor;
- new_cie->ci_code_alignment_factor = code_alignment_factor;
- new_cie->ci_return_address_register = return_address_register;
- new_cie->ci_cie_start = start_cie_ptr;
- new_cie->ci_cie_instr_start = cie_ptr;
- new_cie->ci_dbg = dbg;
- }
- else {
- _dwarf_error(dbg,error,DW_DLE_NO_CIE_FOR_FDE);
- return(DW_DLV_ERROR);
- }
- new_fde->fd_cie = new_cie;
-
- *ret_fde = new_fde;
- return DW_DLV_OK;
- }
-
-
- int
- dwarf_get_fde_range (
- Dwarf_Fde fde,
- Dwarf_Addr *low_pc,
- Dwarf_Unsigned *func_length,
- Dwarf_Ptr *fde_bytes,
- Dwarf_Unsigned *fde_byte_length,
- Dwarf_Off *cie_offset,
- Dwarf_Signed *cie_index,
- Dwarf_Off *fde_offset,
- Dwarf_Error *error
- )
- {
- Dwarf_Debug dbg;
- Dwarf_Fde fde_ptr;
-
- if (fde == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_NULL);
- return(DW_DLV_ERROR);
- }
-
- dbg = fde->fd_dbg;
- if (dbg == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (low_pc != NULL)
- *low_pc = fde->fd_initial_location;
- if (func_length != NULL)
- *func_length = fde->fd_address_range;
- if (fde_bytes != NULL)
- *fde_bytes = fde->fd_fde_start;
- if (fde_byte_length != NULL)
- *fde_byte_length = fde->fd_length;
- if (cie_offset != NULL)
- *cie_offset = fde->fd_cie_offset;
- if (cie_index != NULL)
- *cie_index = fde->fd_cie_index;
- if (fde_offset != NULL)
- *fde_offset = fde->fd_fde_start - dbg->de_debug_frame;
-
- return DW_DLV_OK;
- }
-
-
- int
- dwarf_get_cie_info (
- Dwarf_Cie cie,
- Dwarf_Unsigned *bytes_in_cie,
- Dwarf_Small *version,
- char **augmenter,
- Dwarf_Unsigned *code_alignment_factor,
- Dwarf_Signed *data_alignment_factor,
- Dwarf_Half *return_address_register,
- Dwarf_Ptr *initial_instructions,
- Dwarf_Unsigned *initial_instructions_length,
- Dwarf_Error *error
- )
- {
- Dwarf_Debug dbg;
- Dwarf_Cie cie_ptr;
-
- if (cie == NULL) {
- _dwarf_error(NULL,error,DW_DLE_CIE_NULL);
- return(DW_DLV_ERROR);
- }
-
- dbg = cie->ci_dbg;
- if (dbg == NULL) {
- _dwarf_error(NULL,error,DW_DLE_CIE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (version != NULL)
- *version = DW_CIE_VERSION;
- if (augmenter != NULL)
- *augmenter = cie->ci_augmentation;
- if (code_alignment_factor != NULL)
- *code_alignment_factor = cie->ci_code_alignment_factor;
- if (data_alignment_factor != NULL)
- *data_alignment_factor = cie->ci_data_alignment_factor;
- if (return_address_register != NULL)
- *return_address_register = cie->ci_return_address_register;
- if (initial_instructions != NULL)
- *initial_instructions = cie->ci_cie_instr_start;
- if (initial_instructions_length != NULL)
- *initial_instructions_length = cie->ci_length +
- dbg->de_length_size -
- (cie->ci_cie_instr_start - cie->ci_cie_start);
-
- *bytes_in_cie = (cie->ci_length);
- DW_DLV_OK;
- }
-
-
- int
- dwarf_get_fde_info_for_reg (
- Dwarf_Fde fde,
- Dwarf_Half table_column,
- Dwarf_Addr pc_requested,
- Dwarf_Signed *offset_relevant,
- Dwarf_Signed *register_num,
- Dwarf_Signed *offset,
- Dwarf_Addr *row_pc,
- Dwarf_Error *error
- )
- {
- Dwarf_Debug dbg;
- Dwarf_Fde fde_ptr;
- struct Dwarf_Frame_s fde_table;
- Dwarf_Cie cie;
- Dwarf_Sword i;
-
- if (fde == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (table_column > DW_FRAME_LAST_REG_NUM) {
- _dwarf_error(NULL,error,DW_DLE_FRAME_TABLE_COL_BAD);
- return(DW_DLV_ERROR);
- }
-
- dbg = fde->fd_dbg;
- if (dbg == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (pc_requested < fde->fd_initial_location ||
- pc_requested >= fde->fd_initial_location + fde->fd_address_range) {
- _dwarf_error(dbg,error,DW_DLE_PC_NOT_IN_FDE_RANGE);
- return(DW_DLV_ERROR);
- }
-
- cie = fde->fd_cie;
- if (cie->ci_initial_table == NULL) {
- cie->ci_initial_table = _dwarf_get_alloc(dbg, DW_DLA_FRAME, 1);
- if (cie->ci_initial_table == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- for (i = 0; i < DW_FRAME_LAST_REG_NUM; i++) {
- cie->ci_initial_table->fr_reg[i].ru_is_off = 0;
- cie->ci_initial_table->fr_reg[i].ru_register = DW_FRAME_SAME_VAL;
- cie->ci_initial_table->fr_reg[i].ru_offset = 0;
- }
- if (_dwarf_exec_frame_instr(false, NULL, false, NULL, 0,
- cie->ci_cie_instr_start,
- cie->ci_cie_start + cie->ci_length + dbg->de_length_size,
- cie->ci_initial_table, cie, dbg) <= 0) {
- _dwarf_error(dbg,error,DW_DLE_CIE_INSTR_EXEC_ERROR);
- return(DW_DLV_ERROR);
- }
- }
-
- if (_dwarf_exec_frame_instr (false, NULL, true, pc_requested,
- fde->fd_initial_location, fde->fd_fde_instr_start,
- fde->fd_fde_start + fde->fd_length + dbg->de_length_size,
- &fde_table, cie, dbg) <= 0) {
- _dwarf_error(dbg,error,DW_DLE_FRAME_INSTR_EXEC_ERROR);
- return(DW_DLV_ERROR);
- }
-
- if (register_num != NULL)
- *register_num = fde_table.fr_reg[table_column].ru_register;
- if (offset != NULL)
- *offset = fde_table.fr_reg[table_column].ru_offset;
- if (row_pc != NULL)
- *row_pc = fde_table.fr_loc;
-
- *offset_relevant = (fde_table.fr_reg[table_column].ru_is_off);
- return DW_DLV_OK;
- }
-
-
- int
- dwarf_get_fde_n (
- Dwarf_Fde *fde_data,
- Dwarf_Unsigned fde_index,
- Dwarf_Fde *returned_fde,
- Dwarf_Error *error
- )
- {
- Dwarf_Debug dbg;
-
- if (fde_data == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_PTR_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (*fde_data == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_NULL);
- return(DW_DLV_ERROR);
- }
-
- dbg = (*fde_data)->fd_dbg;
- if (dbg == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (fde_index >= dbg->de_fde_count) {
- return(DW_DLV_NO_ENTRY);
- }
- *returned_fde = (*(fde_data + fde_index));
- return DW_DLV_OK;
- }
-
-
- /*
- Lopc and hipc are extensions to the interface to
- return the range of addresses that are described
- by the returned fde.
- */
- int
- dwarf_get_fde_at_pc (
- Dwarf_Fde *fde_data,
- Dwarf_Addr pc_of_interest,
- Dwarf_Fde * returned_fde,
- Dwarf_Addr *lopc,
- Dwarf_Addr *hipc,
- Dwarf_Error *error
- )
- {
- Dwarf_Debug dbg;
- Dwarf_Sword i;
- Dwarf_Fde fde;
-
- if (fde_data == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_PTR_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (*fde_data == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_NULL);
- return(DW_DLV_ERROR);
- }
-
- dbg = (*fde_data)->fd_dbg;
- if (dbg == NULL) {
- _dwarf_error(NULL,error,DW_DLE_FDE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- for (i = 0; i < dbg->de_fde_count; i++) {
- fde = *(fde_data + i);
- if (pc_of_interest >= fde->fd_initial_location &&
- pc_of_interest < fde->fd_initial_location+fde->fd_address_range)
- break;
- }
- if (i < dbg->de_fde_count) {
- if (lopc != NULL) *lopc = fde->fd_initial_location;
- if (hipc != NULL) *hipc = fde->fd_initial_location +
- fde->fd_address_range - 1;
- *returned_fde = fde;
- return(DW_DLV_OK);
- }
-
- return(DW_DLV_NO_ENTRY);
- }
-
-
- int
- dwarf_expand_frame_instructions (
- Dwarf_Debug dbg,
- Dwarf_Ptr instruction,
- Dwarf_Unsigned i_length,
- Dwarf_Frame_Op **returned_op_list,
- Dwarf_Signed * returned_op_count,
- Dwarf_Error *error
- )
- {
- Dwarf_Sword instr_count;
-
- if (dbg == 0) {
- _dwarf_error(NULL,error,DW_DLE_DBG_NULL);
- return(DW_DLV_ERROR);
- }
-
- if (returned_op_list == 0 || returned_op_count == 0) {
- _dwarf_error(dbg,error,DW_DLE_RET_OP_LIST_NULL);
- return(DW_DLV_ERROR);
- }
-
- instr_count = _dwarf_exec_frame_instr (true, returned_op_list,
- false, NULL, 0,
- instruction, (Dwarf_Ptr)((Dwarf_Unsigned)instruction + i_length),
- NULL, NULL, dbg);
- if (instr_count < 0) {
- _dwarf_error(dbg,error,DW_DLE_FRAME_INSTR_EXEC_ERROR);
- return(DW_DLV_ERROR);
- }
-
- *returned_op_count = instr_count;
- return DW_DLV_OK;
- }
-
-
-
- /*
- Used by rqs. Returns DW_DLV_OK if returns the arrays.
- Returns DW_DLV_NO_ENTRY if no section. ?? (How do I tell?)
- Returns DW_DLV_ERROR if there is an error.
-
- */
- int
- _dwarf_frame_address_offsets(Dwarf_Debug dbg,Dwarf_Addr **addrlist,
- Dwarf_Off **offsetlist,Dwarf_Signed *returncount,Dwarf_Error *err)
- {
- int retval = DW_DLV_OK;
- Dwarf_Signed res;
- Dwarf_Cie *cie_data;
- Dwarf_Signed cie_count;
- Dwarf_Fde *fde_data;
- Dwarf_Signed fde_count;
- Dwarf_Signed i;
- Dwarf_Frame_Op *frame_inst;
- Dwarf_Fde fdep;
- Dwarf_Cie ciep;
- Dwarf_Chain curr_chain = 0;
- Dwarf_Chain head_chain = 0;
- Dwarf_Chain prev_chain = 0;
- Dwarf_Arange arange;
- Dwarf_Unsigned arange_count = 0;
- Dwarf_Addr *arange_addrs = 0;
- Dwarf_Off *arange_offsets = 0;
-
- res = dwarf_get_fde_list(dbg,&cie_data,&cie_count,
- &fde_data,&fde_count,err);
- if(res != DW_DLV_OK) {
- return res;
- }
- for(i = 0; i < cie_count; i++) {
- Dwarf_Off instoff = 0;
- Dwarf_Signed initial_instructions_length = 0;
- Dwarf_Small * instr_end = 0;
- Dwarf_Sword icount = 0;
- int j;
- ciep = cie_data[i];
- instoff =
- ciep->ci_cie_instr_start - dbg->de_debug_frame;
- initial_instructions_length = ciep->ci_length +
- dbg->de_length_size -
- (ciep->ci_cie_instr_start - ciep->ci_cie_start);
- instr_end = ciep->ci_cie_instr_start +
- initial_instructions_length;
- icount = _dwarf_exec_frame_instr(/*make_instr*/true,
- &frame_inst,
- /* search_pc=*/false,
- /*search_pc_val=*/0,
- /*location*/ 0,
- ciep->ci_cie_instr_start,
- instr_end,
- /* Dwarf_frame=*/0,
- /* cie=*/0,
- dbg);
- if(icount < 0) {
- _dwarf_error(dbg,err,DW_DLE_FRAME_INSTR_EXEC_ERROR);
- return(DW_DLV_ERROR);
- }
-
- for(j = 0; j < icount; ++j) {
- if(frame_inst[i].fp_base_op == 0 &&
- frame_inst[i].fp_extended_op == 1) {
- /* is DW_CFA_set_loc */
- Dwarf_Addr add = (Dwarf_Addr)frame_inst[i].fp_offset;
- Dwarf_Off off = frame_inst[i].fp_instr_offset + instoff;
-
- arange = (Dwarf_Arange)
- _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
- if (arange == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- arange->ar_address = add;
- arange->ar_info_offset = off;
- arange_count++;
- curr_chain = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_chain == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- curr_chain->ch_item = arange;
- if (head_chain == NULL)
- head_chain = prev_chain = curr_chain;
- else {
- prev_chain->ch_next = curr_chain;
- prev_chain = curr_chain;
- }
- }
- }
- dwarf_dealloc(dbg,frame_inst,DW_DLA_FRAME_BLOCK);
-
- }
- for(i = 0; i < fde_count; i++) {
- Dwarf_Small *instr_end = 0;
- Dwarf_Sword icount = 0;
- Dwarf_Signed instructions_length = 0;
- Dwarf_Off instoff = 0;
- Dwarf_Off off = 0;
- Dwarf_Addr addr = 0;
- int j;
-
- fdep = fde_data[i];
- off = fdep->fd_initial_loc_pos - dbg->de_debug_frame;
- addr = fdep->fd_initial_location;
- arange = (Dwarf_Arange)
- _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
- if (arange == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- arange->ar_address = addr;
- arange->ar_info_offset = off;
- arange_count++;
- curr_chain = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_chain == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- curr_chain->ch_item = arange;
- if (head_chain == NULL)
- head_chain = prev_chain = curr_chain;
- else {
- prev_chain->ch_next = curr_chain;
- prev_chain = curr_chain;
- }
-
-
- instoff = fdep->fd_fde_instr_start - dbg->de_debug_frame;
- instructions_length = fdep->fd_length +
- dbg->de_length_size -
- (fdep->fd_fde_instr_start - fdep->fd_fde_start);
- instr_end = fdep->fd_fde_instr_start +
- instructions_length;
- icount = _dwarf_exec_frame_instr(/*make_instr*/true,
- &frame_inst,
- /*search_pc=*/false,
- /*search_pc_val=*/0,
- /*location*/ 0,
- fdep->fd_fde_instr_start,
- instr_end,
- /* Dwarf_frame=*/0,
- /* cie=*/0,
- dbg);
- if(icount < 0) {
- _dwarf_error(dbg,err,DW_DLE_FRAME_INSTR_EXEC_ERROR);
- return(DW_DLV_ERROR);
- }
-
- for(j = 0; j < icount; ++j) {
- if(frame_inst[i].fp_base_op == 0 &&
- frame_inst[i].fp_extended_op == 1) {
- /* is DW_CFA_set_loc */
- Dwarf_Addr add = (Dwarf_Addr)frame_inst[i].fp_offset;
- Dwarf_Off off = frame_inst[i].fp_instr_offset + instoff;
- arange = (Dwarf_Arange)
- _dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
- if (arange == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- arange->ar_address = add;
- arange->ar_info_offset = off;
- arange_count++;
- curr_chain = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_chain == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- curr_chain->ch_item = arange;
- if (head_chain == NULL)
- head_chain = prev_chain = curr_chain;
- else {
- prev_chain->ch_next = curr_chain;
- prev_chain = curr_chain;
- }
-
- }
- }
- dwarf_dealloc(dbg,frame_inst,DW_DLA_FRAME_BLOCK);
-
- }
- dwarf_dealloc(dbg,fde_data,DW_DLA_LIST);
- dwarf_dealloc(dbg,cie_data,DW_DLA_LIST);
- arange_addrs = (Dwarf_Addr *)
- _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
- if (arange_addrs == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
- arange_offsets = (Dwarf_Off *)
- _dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
- if (arange_offsets == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return(DW_DLV_ERROR);
- }
-
- curr_chain = head_chain;
- for (i = 0; i < arange_count; i++) {
- Dwarf_Arange ar = curr_chain->ch_item;
- arange_addrs[i] = ar->ar_address;
- arange_offsets[i] = ar->ar_info_offset;
- prev_chain = curr_chain;
- curr_chain = curr_chain->ch_next;
- dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
- dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
- }
- *returncount = arange_count;
- *offsetlist = arange_offsets;
- *addrlist = arange_addrs;
- return retval;
- }
-